package com.mdd.front.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.mdd.common.core.PageResult;
import com.mdd.common.entity.order.Address;
import com.mdd.common.entity.order.Mansion;
import com.mdd.common.entity.order.OrderMenu;
import com.mdd.common.mapper.order.AddressMapper;
import com.mdd.common.mapper.order.MansionMapper;
import com.mdd.common.mapper.order.OrderMenuMapper;
import com.mdd.common.mapper.user.UserMapper;
import com.mdd.common.util.DateUtils;
import com.mdd.common.util.LocationUtils;
import com.mdd.common.util.TimeUtils;
import com.mdd.front.LikeFrontThreadLocal;
import com.mdd.front.service.IAddressService;
import com.mdd.front.validate.commons.PageValidate;
import com.mdd.front.validate.order.AddressCreateValidate;
import com.mdd.front.validate.order.AddressUpdateValidate;
import com.mdd.front.vo.order.AddressIndexVo;
import com.mdd.front.vo.order.AddressVo;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 地址服务类
 * @author shenjian
 * @createTime 2023年02月08日 23:34:00
 */

@Service
public class AddressServiceImpl implements IAddressService {

    @Resource
    AddressMapper addressMapper;

    @Resource
    UserMapper userMapper;

    @Resource
    MansionMapper mansionMapper;

    @Resource
    OrderMenuMapper orderMenuMapper;

    @Override
    public PageResult<AddressVo> list(PageValidate pageValidate) {
        Integer userId = LikeFrontThreadLocal.getUserId();
        Integer pageNo   = pageValidate.getPageNo();
        Integer pageSize = pageValidate.getPageSize();

        QueryWrapper<Address> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("is_delete", 0);
        queryWrapper.eq("user_id", userId);
        queryWrapper.orderByDesc("is_default").orderByDesc("id");
        queryWrapper.select(Address.class, info ->
                !"is_delete".equals(info.getColumn()) &&
                        !"delete_time".equals(info.getColumn()) &&
                        !"update_time".equals(info.getColumn()));

        Page<Address> iPage = this.addressMapper.selectPage(new Page<>(pageNo, pageSize), queryWrapper);
        List<Mansion> mansionList = this.getMansionList(null);
        Map<Integer, List<Mansion>> mansionMap = mansionList.stream().collect(Collectors.groupingBy(Mansion::getId));
        List<AddressVo> list = new LinkedList<>();
        for(Address address : iPage.getRecords()) {
            AddressVo vo = new AddressVo();
            BeanUtils.copyProperties(address, vo);
            List<Mansion> mansions = mansionMap.get(address.getMansionId());
            if (CollectionUtils.isNotEmpty(mansions)) {
                vo.setMansionName(mansions.get(0).getName());
            }
            list.add(vo);
        }
        return PageResult.iPageHandle(iPage.getTotal(), iPage.getCurrent(), iPage.getSize(), list);
    }

    @Override
    public void add(AddressCreateValidate createValidate) {
        Integer userId = LikeFrontThreadLocal.getUserId();
        Assert.notNull(
                this.userMapper.selectById(userId),
                "人员信息不存在");
        Address defaultAddress = this.getDefaultAddress(userId);
        Address address = new Address();
        address.setUserId(userId);
        BeanUtils.copyProperties(createValidate, address);
        if (defaultAddress == null) {
            address.setIsDefault(1);
        } else {
            address.setIsDefault(0);
        }
        address.setIsDelete(0);
        address.setCreateTime(TimeUtils.timestamp());
        this.addressMapper.insert(address);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void edit(AddressUpdateValidate updateValidate) {
        Integer userId = LikeFrontThreadLocal.getUserId();
        long now = TimeUtils.timestamp();
        Address address = this.addressMapper.selectById(updateValidate.getId());
        Assert.notNull(address, "数据错误，该地址数据不存在！");
        Assert.isTrue(userId.equals(address.getUserId()), "当前地址不属于你");
        if (updateValidate.getIsDefault() == 1) {
            if (address.getIsDefault() == 0) {
                Address defaultAddress = this.getDefaultAddress(address.getUserId());
                defaultAddress.setIsDefault(0);
                defaultAddress.setUpdateTime(now);
                this.addressMapper.updateById(defaultAddress);
            }
        }
        BeanUtils.copyProperties(updateValidate, address);
        address.setUpdateTime(now);
        this.addressMapper.updateById(address);
    }

    @Override
    public AddressVo detail(Integer id) {
        Integer userId = LikeFrontThreadLocal.getUserId();
        Address address = this.addressMapper.selectById(id);
        Assert.notNull(address, "数据错误，该地址数据不存在！");
        Assert.isTrue(userId.equals(address.getUserId()), "当前地址不属于你");
        List<Mansion> mansionList = this.getMansionList(address.getMansionId());
        Assert.notEmpty(mansionList, "地址关联的大厦已经被移除，请前往地址管理更改");
        Mansion mansion = mansionList.get(0);
        AddressVo vo = new AddressVo();
        BeanUtils.copyProperties(address, vo);
        if (!mansionList.isEmpty()) {
            vo.setMansionName(mansion.getName());
            vo.setDeliveryTime(mansion.getDeliveryTime());
            vo.setTotalFloor(mansion.getTotalFloor());
        }
        return vo;
    }

    @Override
    public void del(Integer id) {
        Integer userId = LikeFrontThreadLocal.getUserId();
        Address address = this.addressMapper.selectById(id);
        Assert.notNull(address, "数据错误，该地址数据不存在！");
        Assert.isTrue(userId.equals(address.getUserId()), "当前地址不属于你");
        address.setIsDelete(1);
        address.setIsDefault(0);
        address.setDeleteTime(TimeUtils.timestamp());
        this.addressMapper.updateById(address);
    }

    @Override
    public void setDefault(Integer id) {
        Integer userId = LikeFrontThreadLocal.getUserId();
        long now = TimeUtils.timestamp();
        Address address = this.addressMapper.selectById(id);
        Assert.notNull(address, "数据错误，该地址数据不存在！");
        Assert.isTrue(userId.equals(address.getUserId()), "当前地址不属于你");
        if (address.getIsDefault() == 0) {
            Address defaultAddress = this.getDefaultAddress(address.getUserId());
            defaultAddress.setIsDefault(0);
            defaultAddress.setUpdateTime(now);
            this.addressMapper.updateById(defaultAddress);
            address.setIsDefault(1);
        } else {
            address.setIsDefault(0);
        }
        address.setUpdateTime(now);
        this.addressMapper.updateById(address);
    }

    @Override
    public AddressIndexVo getIndexAddressInfo(Integer addressId, Double longitude, Double latitude) {
        Integer userId = LikeFrontThreadLocal.getUserId();
        Address address;
        if (addressId == null) {
            address = this.getDefaultAddress(userId);
        } else {
            address = this.addressMapper.selectById(addressId);
        }
        final AddressIndexVo addressIndexVo = AddressIndexVo.builder().build();
        if (address != null) {
            Assert.isTrue(userId.equals(address.getUserId()), "当前地址不属于你");
            List<Mansion> mansionList = this.getMansionList(address.getMansionId());
            Assert.notEmpty(mansionList, "地址关联的大厦已经被移除，请前往地址管理更改");
            Mansion mansion = mansionList.get(0);
            addressIndexVo.setAddressId(address.getId());
            addressIndexVo.setMansionId(mansion.getId());
            addressIndexVo.setMansionName(mansion.getName());
            if (mansion.getLongitude() != null && mansion.getLatitude() != null) {
                addressIndexVo.setDistance(Math.round(LocationUtils.getDistance(latitude, longitude, mansion.getLatitude(), mansion.getLongitude()).intValue()));
            }
        }
        List<OrderMenu> orderMenus = orderMenuMapper.selectList(new QueryWrapper<OrderMenu>()
                .orderByDesc("day")
                .eq("status", 1)
                .last("limit 1"));
        if (!orderMenus.isEmpty()) {
            OrderMenu orderMenu = orderMenus.get(0);
            addressIndexVo.setDay(orderMenu.getDay());
            addressIndexVo.setMenuId(orderMenu.getId());
            addressIndexVo.setWeek(orderMenu.getWeek());
        } else {
            addressIndexVo.setDay(LocalDate.now());
            addressIndexVo.setWeek(DateUtils.convertWeek(LocalDate.now()));
        }
        return addressIndexVo;
    }

    private Address getDefaultAddress(Integer userId) {
        QueryWrapper<Address> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("is_default", 1);
        queryWrapper.eq("is_delete", 0);
        queryWrapper.eq("user_id", userId);
        return this.addressMapper.selectOne(queryWrapper);
    }

    private List<Mansion> getMansionList(Integer mansionId) {
        QueryWrapper<Mansion> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("is_delete", 0);
        if (mansionId != null) {
            queryWrapper.eq("id", mansionId);
        }
        return this.mansionMapper.selectList(queryWrapper);
    }
}
